#include "GUI.h"
#include <GL/glut.h>
#include <iostream>
using namespace std;

GUIManager::GUIManager()
{
	globalID=0;
}

GUIManager::~GUIManager()
{
	for(int i=0; i<canvas.size();i++)
		canvas[i].~GUICanvas();
}

void GUIManager::AddCanvas(GUICanvas & canvas_)
{
	canvas.push_back(GUICanvas(canvas_));
}

void GUIManager::RemoveCanvas(unsigned index)
{
	canvas.erase(canvas.begin() + index);
}

void GUIManager::DrawCanvas()
{
	for(int i=0; i<canvas.size();i++)
		canvas[i].Draw();
}

void GUIManager::Mouse(unsigned x, unsigned y)
{
	for(int i=0; i<canvas.size(); i++)
	{
		if(x<canvas[i].GetTopX()) continue;
		if(y>canvas[i].GetTopY()) continue;
		if(x>canvas[i].GetBottomX()) continue;
		if(y<canvas[i].GetBottomY()) continue;
		canvas[i].Mouse(x, y);
	}
}
/*

*/

GUICanvas::GUICanvas()
{}

GUICanvas::GUICanvas(unsigned x, unsigned y, unsigned width, unsigned height, unsigned id)
{
	type=CANVAS;
	hide = 0;
	x1 = x;
	y1 = y;
	x2 = x + width;
	y2 = y - height;
	this->width = width;
	this->height = height;
	this->id = id;

	borderThickness=2;
	padding = 5;
	offset = padding;

	borderColor[0]=1.0;
	borderColor[1]=1.0;
	borderColor[2]=1.0;

	bgColor[0]=0.4;
	bgColor[1]=0.1;
	bgColor[2]=0.1;
	alpha=0.8;
}

GUICanvas::~GUICanvas()
{}

void GUICanvas::Draw()
{
	if(hide) return;

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	gluOrtho2D(0,1440,0,900);   // >>> feed screen width and height
	glMatrixMode(GL_MODELVIEW);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	// outline border
	glLoadIdentity();
	glColor3f(borderColor[0],borderColor[1],borderColor[2]);
	glLineWidth(borderThickness);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	glBegin(GL_QUADS);
		glVertex2i(x1,y1);
		glVertex2i(x2,y1);
		glVertex2i(x2,y2);
		glVertex2i(x1,y2);
	glEnd();
	// inside rectangle
	glColor4f(bgColor[0],bgColor[1],bgColor[2],alpha);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glBegin(GL_QUADS);
		glVertex2i(x1,y1);
		glVertex2i(x2,y1);
		glVertex2i(x2,y2);
		glVertex2i(x1,y2);
	glEnd();

	for(int i=0; i<children.size();i++)
	{
		children[i]->Draw();
	}

	glPopMatrix();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glEnable(GL_DEPTH_TEST);
}

void GUICanvas::AddChild(GUICanvas * child)
{
	child->SetXY1(x1+width/2-child->GetWidth()/2, y1-offset);
	child->SetXY2(x1+width/2+child->GetWidth()/2, y1-offset-child->GetHeight());
	offset+=child->GetHeight()+padding;
	children.push_back(child);
}

void GUICanvas::Mouse(unsigned x, unsigned y)
{
	
	for(int i=0; i<children.size(); i++)
	{
		if(x<children[i]->GetTopX()) continue;
		if(y>children[i]->GetTopY()) continue;
		if(x>children[i]->GetBottomX()) continue;
		if(y<children[i]->GetBottomY()) continue;
		children[i]->Mouse(x,y);
	}
}

/*
Text Box
*/

GUITextBox::GUITextBox() 
{
	hide=0; 
	anchor=CENTER_ANCHOR;
	textWrap=true;
	SetWidth(0); 
	SetHeight(0); 
	SetPadding(7);
	textColor[0]=1.0; textColor[1]=1.0; textColor[2]=1.0;
	alpha=0.8;
}

void GUITextBox::CreateField(CFont & font, unsigned x, unsigned y, unsigned numChars, unsigned numLines, unsigned maxLines)
{
	type=TEXTBOX;
	this->font=&font;
	this->x=x;
	this->y=y;
	charsPerLine=numChars;
	this->numLines=numLines;
	this->maxLines=maxLines;
	charHeight=font.getCharLength();
	charLength=charHeight*0.625; // .625 so to bring the characters closer
	SetWidth(charLength*charsPerLine);
	SetHeight(charHeight*numLines);

	text=new char*[maxLines];
	for(int i=0; i<maxLines;i++)
		text[i]=new char[charsPerLine];

	for(int i=0; i<maxLines;i++)
    text[i][0]='\0';
}

void GUITextBox::Write(const char * text_, ...)
{
	if(text_==NULL)
		return;

	va_list list;
	va_start(list, text_);
	 
	if(currLine>=maxLines)
		currLine=0;

	//if(text_wrap)	
	if(strlen(text_)>charsPerLine+1)
	{
		char text2[2048];
		vsprintf(text2, text_, list); 
		unsigned char_index=0;		// keeps track of the remaining letters on the line
		unsigned char_index2=0;		// keeps track of the location in text
		unsigned word_length=0;
		int i=0;
		while(i<strlen(text2))
		{
			if(text2[i]==' ')
			{
				if(char_index2==charsPerLine-1)
				{
					text[currLine][charsPerLine-1]='\0';
					if(currLine==maxLines)
						currLine=0;
					else
						currLine++;
					char_index=0;
					char_index2=0;
				}
				if(char_index2!=0)
				{
					text[currLine][char_index2]=text2[i];
					char_index++;
					char_index2++;
				}
				i++;
			}
			while(text2[i]!=' ' && i<strlen(text2))
			{
				if(word_length>charsPerLine+1)
				{
					cout <<"UMMM...";
				}
				else if (word_length>charsPerLine-char_index-1)
				{
					for(int j=char_index2;j<charsPerLine;j++)
						text[currLine][j-1]=' ';
					text[currLine][charsPerLine-1]='\0';
					currLine++;
					if(currLine==maxLines)
						currLine=0;
					char_index=0;
					char_index2=0;
				}
				word_length++;
				char_index++;
				i++;
			}
			for(int h=0;h<word_length;h++)
			{
				text[currLine][char_index2]=text2[i+h-word_length];
				char_index2++;
			}
			word_length=0;
		}
		for(int j=char_index2; j<charsPerLine;j++)
			text[currLine][j]=' ';
		text[currLine][charsPerLine-1]='\0';
		currLine++;
		if(currLine==maxLines)
			currLine=0;
	}

	//else if(!text_wrap)

	if(strlen(text_)<=charsPerLine+1)
	{
		numChar=strlen(text_);
		vsprintf(text[currLine], text_, list); 
		currLine++;
	}
	va_end(list);
}

void GUITextBox::SetAnchor(Anchor anchor)
{
	this->anchor=anchor;
}

void GUITextBox::Draw()
{
	GUICanvas::Draw();

	// print text
	glColor3f(textColor[0],textColor[1],textColor[2]);
	int offset; // for CENTER_ANCHOR
	if(anchor==CENTER_ANCHOR)
		offset = (charsPerLine-numChar-1)/2*charLength; 

	int i=0;
	while(i<maxLines && text[i][0]!='/0')
	{
		if(anchor==LEFT_ANCHOR)
		{
			font->glPrint(GetTopX()+padding,GetTopY()-(i+1)*(charHeight)-padding,text[i],NULL);
		}

		if(anchor==CENTER_ANCHOR)
		{
			font->glPrint(GetTopX()+padding+offset,GetTopY()-(i+1)*(charHeight)-padding,text[i],NULL);
		}

		i++;
	}
}

GUITextBox & GUITextBox::operator=(const GUITextBox & textField)
{
	// not updated
	font=textField.font;
	hide=textField.hide;
	charsPerLine=textField.charsPerLine;
	numLines=textField.numLines;
	maxLines=textField.maxLines;
	currLine=textField.currLine;
	charHeight=textField.charHeight;
	borderThickness=textField.borderThickness;
	padding=textField.padding;
	textWrap=textField.textWrap;

	text=new char*[maxLines];
	for(int i=0; i<maxLines;i++)
	{
		text[i]=new char[charsPerLine];
		strcpy(text[i],textField.text[i]);
	}
	textColor[0]=textField.textColor[0];
	textColor[1]=textField.textColor[1];
	textColor[2]=textField.textColor[2];
	bgColor[0]=textField.bgColor[0];
	bgColor[1]=textField.bgColor[1];
	bgColor[2]=textField.bgColor[2];
	alpha=textField.alpha;
   
	return *this;
}

void GUITextBox::SetMouseFunc(void(*MouseFunc)(void))
{
	this->MouseFunc = MouseFunc; 
}

void GUITextBox::Mouse(unsigned x, unsigned y)
{
	MouseFunc();
}

GUITextBox::~GUITextBox()
{
   delete [] text;
};